package dpss.node.server;

import java.util.HashMap;

import dpss.commons.CustomLogger;
import dpss.commons.Player;
import dpss.commons.UDPMessage;


/**
 * Processes a DPSS request UDP message and returns a UDP message
 * as a response
 * @author musab.mirza
 *
 */
public class Processor {
	
	private static CustomLogger logger = CustomLogger.getInstance();
	
	private AccountDatabase accountDatabase;

	public Processor(AccountDatabase accountDatabase) {
		this.accountDatabase = accountDatabase;
	}
	
	
	/**
	 * Transfers the account to another Leader server
	 * 
	 * @param username
	 * @param password
	 * @param oldIpAddress
	 * @param newIpAddress
	 * @throws Exception
	 */
	public synchronized void transferAccount(String username, String password,
			String oldIpAddress, String newIpAddress) throws Exception {
		logger.log("Transfer account request (unimplemeneted in processor): " + oldIpAddress + ":" + username);
	}




	/**
	 * Removes a given account
	 * 
	 * @param request
	 * @return
	 */
	public synchronized void suspendAccount(String adminUsername,
			String adminPassword, String ipAddress, String usernameToSuspend) throws Exception{
		
		logger.log("Suspend account request: " + ipAddress + ":" + adminUsername);

		if (!adminUsername.equalsIgnoreCase("admin")) {
			throw new Exception("You are not an admin");
		}

		try {
			if (!accountDatabase.getAccount("admin").getPassword()
					.equalsIgnoreCase(adminPassword.trim())) {
				throw new Exception("Invalid password");
			}
		} catch (Exception e) {
			throw new Exception("Account does not exist: admin");
		}

		try {
			accountDatabase.removeAccount(usernameToSuspend);
			logger.log("Account suspended: " + ipAddress + ":" + usernameToSuspend);
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}

		
	}

	/**
	 * Gets the status of players (online and offline)
	 * 
	 * @param request
	 * @return
	 */
	public synchronized String getPlayersStatus(String adminUsername,
			String adminPassword, String ipAddress) throws Exception {
		logger.log("Get players status request from: " + ipAddress + ":" + adminUsername);

		if (!adminUsername.equalsIgnoreCase("admin")) {
			throw new Exception("You are not an admin");
		}

		try {
			if (!accountDatabase.getAccount("admin").getPassword()
					.equalsIgnoreCase(adminPassword.trim())) {
				throw new Exception("Invalid password");
			}
		} catch (Exception e) {
			throw new Exception("Account does not exist: admin");
		}

		logger.log("Players status returned to: " + ipAddress + ":" + adminUsername);
		return accountDatabase.getPlayersInfo();
	}

	/**
	 * Signs out a player
	 * 
	 * @param request
	 * @return
	 */
	public synchronized void playerSignOut(String username, String ipAddress) throws Exception {
		
		logger.log("Player sign out request: " + ipAddress + ":" + username);
		try {
			accountDatabase.getAccount(username).setOnline(false);
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
		logger.log("Player signed out: " + ipAddress + ":" + username);
	}

	/**
	 * Signs in a player
	 * 
	 * @param request
	 * @return
	 */
	public synchronized HashMap<String, String> playerSignIn(String username, String password,
			String ipAddress) throws Exception{
		
		logger.log("Player sign in request: " + ipAddress + ":" + username);
		
		// Process...
		Player p = null;
		try {
			p = accountDatabase.getAccount(username);
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
		
		if (!(p.getPassword().trim().equalsIgnoreCase(password))) {
			throw new Exception("Incorrect password");
		}

		if (p.isOnline()) {
			throw new Exception("You are already signed in from another IP");
		}

		p.setOnline(true);

		
		// Respond
		HashMap<String, String> toReturn = new HashMap<String, String>();
		toReturn.put("firstName", p.getFirstName());
		toReturn.put("lastName", p.getLastName());
		toReturn.put("age", p.getAge().toString());

		logger.log("Player signed in: " + p.getUsername());
		return toReturn;
	}

	

	/**
	 * Creates a player account
	 * 
	 * @param data
	 * @return
	 */
	public synchronized void createPlayerAccount(String firstName,
			String lastName, short age, String username, String password,
			String ipAddress) throws Exception{
		
		
		logger.log("Create player request with username: " + username + " from IP: " + ipAddress);

		username = username.trim();
		if (username.equalsIgnoreCase("admin")) {
			throw new Exception(
					"The account 'admin' is reserved and cannot be registered");
		}

		Player p = null;

		// Validation on player account values
		try {
			p = new Player(username, password, (int) age, ipAddress, firstName,
					lastName, true);
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}

		// Account addition validation
		try {
			accountDatabase.addAccount(p);
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
		
		logger.log("New account created: " + username );
		
	}
	
}
